///////////////////////////////////////////////////
/// toto Code
/// $Id: thread.cc 2 2009-12-14 12:41:06Z tonyjobmails $
/// $Date: 2009-12-14 12:41:06 +0000 (Mon, 14 Dec 2009) $
/// $Author: tonyjobmails $
/// $Revision: 2 $
/// E-mail: tonyjobmails@gmail.com
/// filename: thread.cc
/// function: 线程基类的定义
///////////////////////////////////////////////////

#include "thread.h"

namespace toto
{
	///////////////////
	/// @brief 线程开始
	/// @return 成功与否
	bool xthread::start()
	{
		if(this->is_alive())
		{
			/// 线程已创建
#ifdef _TOTO_DEBUG
			std::cout << "[线程开启]线程(" << this->name << ")已开启" << std::endl;
#endif
			return true;
		}
		
		pthread_attr_t attr;
		pthread_attr_init(&attr);
		if(this->is_joinable())
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
		if(pthread_create(&this->thread, &attr, xthread::thread_func, this) != 0)
		{
#ifdef _TOTO_DEBUG
			std::cout << "[线程创建]线程(" << this->name << ")创建失败" << std::endl;
#endif
			return false;
		}
		pthread_attr_destroy(&attr);
		this->mutex.lock();
		if(!this->is_alive())
			this->cond.wait(this->mutex);
		this->mutex.unlock();
	}
	
	///////////////////
	/// @brief 线程方法
	/// @param arg：参数
	/// @return 成功与否
	static bool xthread::thread_func(void *arg)
	{
		xthread *thread = (xthread *)arg;
		
		thread->mutex.lock();
		thread->state = THREAD_STATE_ALIVE;
		thread->cond.broadcast();
		thread->mutex.unlock();
		
		/// 阻塞所有信号
		sigset_t sig_mask;
		sigfillset(&sig_mask);
		pthread_sigmask(SIG_SETMASK, &sig_mask, NULL);
		
		/// 线程主调函数
		this->run();
		
		thread->mutex.lock();
		/// 线程结束
		thread->end();
		thread->cond.broadcast();
		thread->mutex.unlock();
		
		if(!this->is_joinable())
		{
			thread->mutex.lock();
			if(thread->is_alive())
				thread->cond.wait(thread->mutex);
			thread->mutex.unlock();
			delete thread;
			thread = NULL;
		}
	}
	
	///////////////////
	/// @brief 等待线程结束
	void xthread::join()
	{
		if(this->thread && joinable)
		{
			this->mutex.lock();
			if(this->is_alive())
				this->cond.wait();
			this->mutex.unlock();
			pthread_join(this->thread, NULL);
			this->thread = 0;
		}
	}
};